/**
 * Copyright © 2018 The Thingsboard Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.thingsboard.rule.engine.play;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.thingsboard.rule.engine.api.*;
import org.thingsboard.rule.engine.api.util.TbNodeUtils;
import org.thingsboard.server.common.data.plugin.ComponentType;
import org.thingsboard.server.common.msg.TbMsg;

import java.io.IOException;
import java.util.Iterator;

import static org.thingsboard.server.common.data.msg.TbNodeConnectionType.SUCCESS;


/**
 * Created by mshvayka on 10.08.18.
 */
@RuleNode(
        type = ComponentType.ENRICHMENT,
        name = "将遥测数据总和放到metadata中",
        configClazz = TbGetSumIntoMetadataConfiguration.class,
        nodeDescription = "计算遥测数据的总和，这些字段以指定的前缀开头，并将结果添加到metadata中",
        nodeDetails = "如果msg有效载荷中的字段以＜code＞Input Key＜/code＞开头，则将这些字段的总和添加到元数据中。",
        uiResources = {"static/rulenode/custom-nodes-config.js"},
        configDirective = "tbEnrichmentNodeSumIntoMetadataConfig",
        icon = "call_split")
public class TbGetSumIntoMetadata implements TbNode {

    private static final ObjectMapper MAPPER = new ObjectMapper();

    private TbGetSumIntoMetadataConfiguration config;
    private String inputKey;
    private String outputKey;

    //初始化该属性集节点，启动项目时执行
    @Override
    public void init(TbContext ctx, TbNodeConfiguration configuration) throws TbNodeException {
        //加载配置
        this.config = TbNodeUtils.convert(configuration, TbGetSumIntoMetadataConfiguration.class);
        inputKey = config.getInputKey();
        outputKey = config.getOutputKey();
    }

    //使用了该node的时候调用，ctx是本次调用规则链的上下文
    @Override
    public void onMsg(TbContext ctx, TbMsg msg) {
        double sum = 0;
        boolean hasRecords = false;
        try {
            //将消息体中的数据转换成JsonNode对象
            JsonNode jsonNode = MAPPER.readTree(msg.getData());
            Iterator<String> iterator = jsonNode.fieldNames();
            while (iterator.hasNext()) {
                String field = iterator.next();
                //如果字符串的开头是inputKey，那么将节点中的值进行累加
                if (field.startsWith(inputKey)) {
                    sum += jsonNode.get(field).asDouble();
                    hasRecords = true;
                }
            }
            //有数值类型才继续后面的步骤
            if (hasRecords) {
                //将合计的值写入到输出变量中
                msg.getMetaData().putValue(outputKey, Double.toString(sum));
                //上下文调用下一个节点，返回success并将数据往下传
                ctx.tellNext(msg, SUCCESS);
            } else {
                //输出错误
                ctx.tellFailure(msg, new Exception("Message doesn't contains the Input Key: " + inputKey));
            }
        } catch (IOException e) {
            ctx.tellFailure(msg, e);
        }
    }

    @Override
    public void destroy() {

    }
}
